﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Xml;
using System.Xml.Serialization;
using Types.Enumerations;

namespace Contracts.Caching
{
	public class CacheProviderSection : IConfigurationSectionHandler
	{
		#region IConfigurationSectionHandler Members

		public object Create(object parent, object configContext, System.Xml.XmlNode section)
		{
			CacheProviderSettings settings = null;
			if (section == null)
				return settings;

			settings = new CacheProviderSettings();

			string sEnumStr = section.Attributes["ProviderName"].InnerText;
			Array enumValues = Enum.GetValues(typeof(EnumCacheProviders));
			for (int i = 0; i < enumValues.Length; i++)
			{
				if (Enum.GetName(typeof(EnumCacheProviders), enumValues.GetValue(i)) == sEnumStr)
				{
					settings.ProviderName = (EnumCacheProviders)enumValues.GetValue(i);
					break;
				}
			}

			string sCacheTypeEnumStr = section.Attributes["CacheType"].InnerText;
			Array enumCacheTypeValues = Enum.GetValues(typeof(EnumCacheType));
			for (int i = 0; i < enumCacheTypeValues.Length; i++)
			{
				if (Enum.GetName(typeof(EnumCacheType), enumCacheTypeValues.GetValue(i)) == sCacheTypeEnumStr)
				{
					settings.CacheType = (EnumCacheType)enumCacheTypeValues.GetValue(i);
					break;
				}
			}

			// set default
			settings.RefreshMethod = EnumFileDependentCacheRefreshMethod.PullViaUNCPath;

			if (section.Attributes["RefreshMethod"] != null)
			{
				string sRefreshMethodEnumStr = section.Attributes["RefreshMethod"].InnerText;
				Array enumRefreshMethodValues = Enum.GetValues(typeof(EnumFileDependentCacheRefreshMethod));
				for (int i = 0; i < enumRefreshMethodValues.Length; i++)
				{
					if (Enum.GetName(typeof(EnumFileDependentCacheRefreshMethod), enumRefreshMethodValues.GetValue(i)) == sRefreshMethodEnumStr)
					{
						settings.RefreshMethod = (EnumFileDependentCacheRefreshMethod)enumRefreshMethodValues.GetValue(i);
						break;
					}
				}
			}

			settings.CacheItems = new List<CacheItem>();
			foreach (XmlElement xEl in section.SelectNodes(@"./CacheItems/CacheItem"))
			{
				if (settings.CacheType == EnumCacheType.ClientCache)
				{
					// Client cache icin ihtiyacım olan config parametreleri sadece bunlar.
					CacheItem ci = new CacheItem();
					ci.MinutesToExpire = Convert.ToInt32(xEl.GetAttribute("MinutesToExpire"));
					ci.CacheItemName = xEl.GetAttribute("CacheItemName");
					ci.CacheType = settings.CacheType;
					if (section.Attributes["FileDependencyFolder"] != null)
						ci.FileDependencyFolder = section.Attributes["FileDependencyFolder"].InnerText;


					if (!string.IsNullOrEmpty(xEl.GetAttribute("TypedDatasetName")))
					{
						ci.TypedDsName = Type.GetType(xEl.GetAttribute("TypedDatasetName"));
						ci.InvokeDirectly = true;

					}
					else
					{
						ci.InvokeDirectly = false;
						ci.Interfacename = Type.GetType(xEl.GetAttribute("Interfacename"));
						ci.MethodName = xEl.GetAttribute("MethodName");
					}



					ci.RefreshMethod = settings.RefreshMethod;
					settings.CacheItems.Add(ci);
				}
				else if (settings.CacheType == EnumCacheType.ServerCache)
				{
					CacheItem ci = new CacheItem();
					ci.CacheItemName = xEl.GetAttribute("CacheItemName");
					ci.MinutesToExpire = Convert.ToInt32(xEl.GetAttribute("MinutesToExpire"));
					ci.CacheType = settings.CacheType;
					if (section.Attributes["FileDependencyFolder"] != null)
						ci.FileDependencyFolder = section.Attributes["FileDependencyFolder"].InnerText;

					if (!string.IsNullOrEmpty(xEl.GetAttribute("TypedDatasetName")))
					{
						ci.TypedDsName = Type.GetType(xEl.GetAttribute("TypedDatasetName"));
						ci.InvokeDirectly = true;

					}
					else
					{
						ci.InvokeDirectly = false;
						ci.Interfacename = Type.GetType(xEl.GetAttribute("Interfacename"));
						ci.MethodName = xEl.GetAttribute("MethodName");
					}


					ci.RefreshMethod = settings.RefreshMethod;
					settings.CacheItems.Add(ci);
				}
			}
			return settings;
		}

		#endregion


	}

	public class CacheProviderSettings
	{
		private EnumCacheProviders mProviderName;
		private EnumCacheType mCacheType;
		private List<CacheItem> mCacheItem;
		private string mCacheFileDependencyFolder;
		private EnumFileDependentCacheRefreshMethod mRefreshMethod;

		[XmlAttribute()]
		public EnumCacheProviders ProviderName
		{
			get { return mProviderName; }
			set { mProviderName = value; }
		}
		[XmlAttribute()]
		public EnumCacheType CacheType
		{
			get { return mCacheType; }
			set { mCacheType = value; }
		}

		[XmlArray()]
		public List<CacheItem> CacheItems
		{
			get { return mCacheItem; }
			set { mCacheItem = value; }
		}
		[XmlAttribute()]
		public string FileDependencyFolder
		{
			get { return mCacheFileDependencyFolder; }
			set { mCacheFileDependencyFolder = value; }
		}

		[XmlAttribute()]
		public EnumFileDependentCacheRefreshMethod RefreshMethod
		{
			get { return mRefreshMethod; }
			set { mRefreshMethod = value; }
		}

	}


	public class CacheItem
	{
		private string mCacheItemName;
		private Type mImplementedInterfaceName;
		private string mInterfaceMethodNameToFillCache;
		private int mMinutesToExpire;
		private EnumCacheType mCacheType;
		private Type mTypedDatasetTypeName;
		private string mCacheFileDependencyFolder;

		private EnumFileDependentCacheRefreshMethod mRefreshMethod;

		public bool InvokeDirectly;

		[XmlAttribute()]
		public Type Interfacename
		{
			get { return mImplementedInterfaceName; }
			set { mImplementedInterfaceName = value; }
		}

		[XmlAttribute()]
		public Type TypedDsName
		{
			get { return mTypedDatasetTypeName; }
			set { mTypedDatasetTypeName = value; }
		}

		[XmlAttribute()]
		public string MethodName
		{
			get { return mInterfaceMethodNameToFillCache; }
			set { mInterfaceMethodNameToFillCache = value; }
		}

		[XmlAttribute()]
		public int MinutesToExpire
		{
			get { return mMinutesToExpire; }
			set { mMinutesToExpire = value; }
		}

		[XmlAttribute()]
		public string CacheItemName
		{
			get { return mCacheItemName; }
			set { mCacheItemName = value; }
		}

		public EnumCacheType CacheType
		{
			get { return mCacheType; }
			set { mCacheType = value; }
		}

		public string FileDependencyFolder
		{
			get { return mCacheFileDependencyFolder; }
			set { mCacheFileDependencyFolder = value; }
		}

		public EnumFileDependentCacheRefreshMethod RefreshMethod
		{
			get { return mRefreshMethod; }
			set { mRefreshMethod = value; }
		}

	}

}
